//
// Created by LU on 2022/10/19.
//
#include "Logger.h"
using namespace yazi::utility;

#include <time.h>
#include <string.h>
#include <stdexcept>
#include <iostream>
//#include <stdio.h>
#include <stdarg.h>

const char * Logger::s_level[LEVEL_COUNT] = {
        "DEBUG",
        "INFO",
        "WARN",
        "ERROR",
        "FATAL",
};

Logger * Logger::m_instance = NULL;


Logger::Logger(): m_level(DEBUG), m_max(0), m_len(0) //设置默认值
{
 std::cout << "start" << endl;
}

Logger::~Logger()
{
    close();
    std::cout << "end" << endl;
}

Logger *Logger::instance()
{
    if (m_instance == NULL){
        m_instance = new Logger();
    }
    return m_instance;
}

void Logger::destory()
{
    delete m_instance;
}

void Logger::open(const string &filename)
{
    m_filename = filename;
    m_fout.open(filename, ios::app);
    if (m_fout.fail())
    {
        throw std::logic_error("open filename failed "+ filename);
    }
    m_fout.seekp(0, ios::end);
    m_len = m_fout.tellp();
}

void Logger::close()
{
    m_fout.close();
}

void Logger::log(Level level, const char * file , int line, const char * format, ...)
{
    if (m_level > level)
    {
        return;
    }
    if(m_fout.fail())
    {
        throw std::logic_error("open filename failed " + m_filename);
    }
    time_t ticks = time(NULL);
    struct tm * ptm = localtime(&ticks);
    char timestamp[32];
    memset(timestamp, 0, sizeof(timestamp));
    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", ptm);
    const char * fmt = "%s %s %s:%d";
    int size = snprintf(NULL, 0, fmt, timestamp, s_level[level], file, line);
    if (size > 0)
    {
        char * buffer = new char[size+1];
//        memset(buffer, 0, size+1);
        snprintf(buffer, size+1,fmt, timestamp, s_level[level], file, line);
        buffer[size] = 0;
        m_fout << buffer;
        m_len += size;
//        std::cout << buffer << std::endl;
        delete [] buffer;
    }
    va_list arg_ptr;
    va_start(arg_ptr, format);
    size = vsnprintf(NULL, 0, format, arg_ptr);
    va_end(arg_ptr);
    if (size > 0)
    {
        char * content = new char[size+1];
        va_start(arg_ptr, format);
        vsnprintf(content, size+1, format, arg_ptr);
        va_end(arg_ptr);
        std::cout << content << std::endl;
        m_fout << ' ';
        m_fout << content;
        m_len += size;
        delete [] content;
    }
    m_fout << '\n';
    m_fout.flush();

    if (m_len >= m_max && m_max >0)
    {
        rotate();
    }
//    std::cout << timestamp << std::endl;
//    std::cout << file << std::endl;
//    std::cout << line << std::endl;
//    std::cout << format << std::endl;
}

void Logger::rotate()
{
    close();
    time_t ticks = time(NULL);
    struct tm* ptm = localtime(&ticks);
    char timestamp[32];
    memset(timestamp, 0, sizeof(timestamp));
    strftime(timestamp, sizeof(timestamp), ".%Y-%m-%d_%H-%M-%S", ptm);
    string filename = m_filename + timestamp;
    if (rename(m_filename.c_str(), filename.c_str()) != 0)
    {
        throw std::logic_error("rename log file failed: " + string(strerror(errno)));
    }
    open(m_filename);
}
